#pragma once

#ifndef DLL_VECTOR2_H
#define DLL_VECTOR2_H
#endif


class vector2{
public:
	float x,y;
	
	vector2():x(0),y(0){}

	~vector2(){};

	vector2( float x,float y ):x(x),y(y){}
	operator float*() {return &x;}
	operator const float *() {return &x;}
	float &operator[](int n) {return (&x)[n];}
	float operator[](int n)const {return (&x)[n];}
	vector2* operator-()const {return new vector2( -x,-y );}
	vector2* operator*( float scale )const {return new vector2(x*scale,y*scale);}
	vector2* operator*( const vector2 *q )const
		{return new vector2( x*q->x,y*q->y );}
	vector2* operator/( float scale )const
		{return new vector2( x/scale,y/scale );}
	vector2* operator/( const vector2 *q )const
		{return new vector2( x/q->x,y/q->y );}
	vector2* operator+( vector2 *q )const
		{return new vector2( x+q->x,y+q->y );}
	vector2* operator-( vector2 *q )const
		{return new vector2( x-q->x,y-q->y );}
	vector2* operator*=( float f ) {x*=f;y*=f;return this;}
	vector2* operator*=( const vector2 *q ) {x*=q->x;y*=q->y;return this;}
	vector2* operator/=( float f ) {f=1.0f/f;x*=f;y*=f;return this;}
	vector2* operator/=( const vector2 *q ) {x/=q->x;y/=q->y;return this;}
	vector2* operator+=( const vector2 *q ) {x+=q->x;y+=q->y;return this;}
	vector2* operator-=( const vector2 *q ) {x-=q->x;y-=q->y;return this;}
	
	bool operator<( const vector2 *q )const
	{	if( fabs(x-q->x)>FLOAT_EPSILON ) return x<q->x ? true : false;
		return fabs(y-q->y)>FLOAT_EPSILON && y<q->y;}
		
	bool operator==( vector2* q )const
		{return (
				fabs(x-q->x)<=FLOAT_EPSILON &&
				fabs(y-q->y)<=FLOAT_EPSILON);}
	
	bool operator!=( const vector2 *q )const
		{return (
				fabs(x-q->x)>FLOAT_EPSILON ||
				fabs(y-q->y)>FLOAT_EPSILON);}
	
	void Set (float X, float Y){x=X;y=Y;};
	
	float Dot( const vector2 *q )const {return x*q->x+y*q->y;}
	float Angle( const vector2 *q )const {return acos(Dot(q));};
	float Cross( const vector2 *q )const
		{return ( y*q->x-x*q->y );}
	
	float SqLength()const {return (x*x+y*y);}
	float Length()const {return sqrtf(x*x+y*y);}
	float Distance(const vector2 *q)const
		{return sqrtf((x-q->x)*(x-q->x)+(y-q->y)*(y-q->y));}
	
	vector2* Normalized()const {float l=1.0f/Length();return new vector2( x*l,y*l );}
	void Normalize() {float l=1.0f/Length();x*=l;y*=l;}
	void Scale(float f){x*=f;y*=f;};
	float Yaw()const {return atan2f(y,x);}
	
	void Clear() {x=y=0;}
};





class vector2list;


class vector2link{
private :
	friend vector2link* Nullvector2link();
	friend inline void Unlinkvector2(vector2link* lnk);

public :
	
	vector2link(){;};
	~vector2link(){Unlinkvector2(this);};
	vector2list* list;
	vector2link* next;
	vector2link* prev;
	vector2* v;
	
	int InsertAfter(vector2link* after);
	int InsertBefore(vector2link* after);
	
};

vector2link* Nullvector2();

class vector2list{
public :
	
	vector2link* head;
	vector2link* tail;
	int count;

	vector2list(){		head	=	0;
						tail	=	0;
						count	=	0;
	};
	~vector2list(){		while (head!=0)
						{
							vector2link* temp(head);
							head=head->next;
							delete temp;
						};
	};
	vector2list* Copy(){
							vector2list* copy = new vector2list();
							vector2link* lnk = head;
							while (lnk!=0)
							{
								copy->AddLast(lnk->v);
								lnk=lnk->next;
							};
							return copy;
						};
	vector2link* AddLast(vector2* vector){
							vector2link* lnk=	new vector2link();
							lnk->v			=	vector;
							lnk->list		=	this;
							
							if (head==0)
							{
								head		=	lnk;
								lnk->prev	=	0;
							}
							else
							{
								tail->next	=	lnk;
								lnk->prev	=	tail;
							};
							tail			=	lnk;
							lnk->next		=	0;
							count++;
							return lnk;
	};
	vector2link* AddFirst(vector2* vector){
							vector2link* lnk=	new vector2link();
							lnk->v			=	vector;
							lnk->list		=	this;
							
							if (tail==0)
							{
								tail		=	lnk;
								lnk->next	=	0;
							}
							else
							{
								head->prev	=	lnk;
								lnk->next	=	head;
							};
							head			=	lnk;
							lnk->prev		=	0;
							count++;
							return lnk;
	};
	vector2link* Find(vector2* vector){
							if (head==0) return 0;
							vector2link* l = head;
							while (l!=0)
							{
								if (l->v==vector) return l;
								l=l->next;
							};
							return 0;
	};

};


inline void Unlinkvector2(vector2link* lnk){
	vector2list* l = lnk->list;
	
	if (lnk==l->head)
	{
		if (lnk==l->tail)
		{
			l->head=0;
			l->tail=0;
		}
		else
		{
			l->head=lnk->next;
			l->head->prev=0;
		};
	}
	else
	{
		if (lnk==l->tail)
		{
			l->tail=l->tail->prev;
			l->tail->next=0;
		}
		else
		{
			lnk->next->prev=lnk->prev;
			lnk->prev->next=lnk->next;
		};
	};
	lnk->next=0;
	lnk->prev=0;
	lnk->list->count--;
};

